package com.classes;

import java.io.*;
import java.util.*;
import java.text.*;

import com.mbbmap.util.EnhancedException;

/**
 * SystemLogManager is implemented as a variant of a Singleton
 * which controls logging of error messages and warnings to the system log.
 * The location of the system log is determined by the "SysLogFile" entry in
 * the <i>system.properties</i> file. If no such entry is defined, then it will create and log to
 * the file <i>system.log</i> in the current working directory.
 * <p>
 * Usage of this class assumes that the ConfigManager class has been
 * loaded with the properties from the config file.
 * <p>
 */
public class LogManager {
	private static PrintWriter log = null;
	private static String logFile = null;		private static String logSize = null;
	
	private static String orifilename = "";
	
	private static String tempDate = "";
	private static LogManager instance = null;

	private static final String defaultFilePath = "/system.log";
	//config declaration
	private static final String CONFIG_FILE = "/log.properties";
	private static final String LOG_FILE_PATH = "log.file.path";		private static final String LOG_FILE_SIZE = "log.file.size";
	private static final java.util.Properties appCfg = new java.util.Properties();
	private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");

	private LogManager() {
		super();
	   try {
			InputStream stream = this.getClass().getResourceAsStream(
					CONFIG_FILE);
			if (stream != null)
				appCfg.load(stream);
			else
				throw new Exception("Input Stream is null");
			if ((logFile = appCfg.getProperty(LOG_FILE_PATH)) == null) {
					System.out.println("here:" + logFile);
				logFile = defaultFilePath;
			}
					System.out.println("here:" + logFile);								if ((logSize = appCfg.getProperty(LOG_FILE_SIZE)) == null) {						System.out.println("size here:" + logSize);						logSize = "200";				}
			stream.close();
		} catch (Exception e) {
			System.err.println("Error loading file " + CONFIG_FILE);
			System.err.println(e.getMessage());
			e.printStackTrace();
		}
	}

    /**
     * Returns the single instance, creating one if it's the
     * first time this method is called.
     *
     * @return SystemLogManager. The single instance.
     */
	public static LogManager getInstance(String Path) {

		//thread-safe implementation
		if (instance == null) {
			synchronized (LogManager.class) {
				if (instance == null) {
					instance = new LogManager();
						logFile = Path;
					System.out.println("here:" + logFile);
				//if ((logFile = ConfigManager.getInstance().get("SysLogFile")) == null) {
					System.out.println("cnfig logfile path:" + appCfg.getProperty("LOG_FILE_PATH"));
					System.out.println("logfile path:" + logFile);

					Calendar cal = Calendar.getInstance();
					tempDate = dateFormatter.format(cal.getTime()).toString();										orifilename = logFile;
					logFile = logFile + tempDate + ".log";										//check the size for each log file					//added by Hong Lian 20131003				    int fileflag = 0;				    while(fileflag!=-1){					    File file = new File(logFile);					    fileflag = LogManager.checkfile(file, fileflag);					    if(fileflag!=-1){					    	logFile = orifilename + tempDate + "_" + fileflag + ".log";					    }				    }
				}
			}
		}
		return instance;
	}

    /**
     * Returns the single instance, creating one if it's the
     * first time this method is called.
     *
     * @return SystemLogManager. The single instance.
     */
	public static LogManager getPrefixInstance(String Path,String strPrefix) {

		//thread-safe implementation
		if (instance == null) {
			synchronized (LogManager.class) {
				if (instance == null) {
					instance = new LogManager();
						logFile = Path;
					System.out.println("here:" + logFile);
				//if ((logFile = ConfigManager.getInstance().get("SysLogFile")) == null) {
					System.out.println("cnfig logfile path:" + appCfg.getProperty("LOG_FILE_PATH"));
					System.out.println("logfile path:" + logFile);

					Calendar cal = Calendar.getInstance();
					String tempDate = dateFormatter.format(cal.getTime()).toString();
					logFile = logFile + strPrefix + "_" + tempDate + ".log";
				}
			}
		}
		return instance;
	}
	/**
     * Logs error messages to the log
     *
     * @param EnhancedException The necessary information regarding the error
     * would be retrieved from the EnhancedException object. This includes the
     * exception location in the code (which class, which method, etc), and
     * extra error messages.
     * <p>
     * Ordinarily, this is coded as follows:
     * <p><pre><code>
     * try {
	 *     //statements
     * } catch (Exception e) {
     *     EnhancedException ex = new EnhancedException(e.getMessage());
     *     ex.setExceptionLocation("className_methodName_###");
     *     ex.setExtraMessage("any extra message that will be helpful");
     *     SystemLogManager.getInstance().logError(ex);
     * }
     * </code></pre>
     * <p>
     * If logging does not occur within a catch block, then the EnhancedException
     * should be created with an empty string ("").
     */
	public void logError(EnhancedException e) {
		log(e.getExceptionLocation(), e.getExtraMessage(), e.getMessage());
	}

	/**
     * Logs info or status messages to the log
     *
     * @param message The info message to be logged
     */
	public void logMsg(String msg) {
		log("INFO", msg, null);
	}
	public void logWarnMsg(String msg){		log("WARNING!!!", msg,null);	}
	private void getResources() throws Exception {
		//set with file write append (second boolean parameter)
		//set without autoflush in PrintWriter
		log = new PrintWriter(new FileWriter(logFile, true));
	}

	private void releaseResources() {
		if (log != null)
			log.close();
	}

	//NOTE: As long as ALL modifications to the content of the log is done
	//      through this synchronized method, there is no need to synchronize
	//      the rest of the methods.

	private synchronized void log(String location,
		String extraMessage, String mainMessage) {

		Date todaysDate = Calendar.getInstance().getTime();
		DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,
		DateFormat.SHORT);

		try {
			//added by Hong Lian check file size is always on
			
			//check the size for each log file
			//added by Hong Lian 20131003
		    int fileflag = 0;
		    while(fileflag!=-1){
			    File file = new File(logFile);
			    fileflag = LogManager.checkfile(file, fileflag);
			    if(fileflag!=-1){
			    	logFile = orifilename + tempDate + "_" + fileflag + ".log";
			    }
		    }
		    
	    	//start new file
	    	getResources();
			//logging of error messages that do not contain a thrown exception
			if ((mainMessage == null) || (mainMessage.length() < 1)) {
				log.println("[" + df.format(todaysDate) + "] (" +
					location + ") : " +
					extraMessage);
			}
			//logging of error messages that encapsulates a thrown exception
			else {
				log.println("[" + df.format(todaysDate) + "] (" +
					location + ") : " +
					extraMessage + " | " +
					"(" + mainMessage + ")");

			}
			log.flush();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
		releaseResources();
	}		private static int checkfile(File file, int fileflag){			   	    /*	     * To get the size of a file, use	     * long length() method of Java File class.	     *	     * This method returns size of a particular file in bytes. It returns 0L	     * if file does not exists, and unspecified if file is a directory.	     *	     */	     long fileSize = file.length();	   	     //System.out.println("File size in bytes is: " + fileSize);	     //System.out.println("File size in KB is : " + (double)fileSize/1024);	     //System.out.println("File size in MB is :" + (double)fileSize/(1024*1024));	     long checksize = Integer.parseInt(logSize)*1024*1024;	     if(fileSize>checksize){	    	fileflag = fileflag+1;	     }else{	    	 fileflag = -1;	     }	     	     return fileflag;	}	
}
